// EEGAnalysis.cpp : Defines the exported functions for the DLL application.
//

#include "stdafx.h"

#include "resource.h"

#include "waconsts.h"
#include "config.h"
#include "EEGAnalysis.h"

#include "eeg_exceptions.h"
#include "datastore.h"
#include "waitbox.h"

//#include "fftcalculator.h"
//#include "fftmainfrm.h"

#include "utilities.h"

#include "dsacalculator.h"
#include "dsasinglegraph.h"
#include "DSAGraphView.h"
#include "DSAMainFrm.h"

#include "fftcalculator.h"
#include "FFTGraphView.h"
#include "FFTMainFrm.h"

#include "mapcalculator.h"
#include "mapframe.h"
#include "mapsinglegraph.h"
#include "mapgraphview.h"
#include "mapmainfrm.h"

HMODULE hDllModule;
ULONG_PTR           gdiplusToken;
CAppModule _Module;

FFT_CalcParams *fft_cp = 0;

DSA_CalcParams *dsa_cp = 0;
std::vector< DSA_SingleGraph > dsa_views;

MAP_Descriptor *map_des = 0;

 void DefaultErrorHandler(LPCWSTR what){
	MessageBox(0, what, _T("Error"), 0);
	 //::MessageBox(::GetForegroundWindow()

 }
//global variables
 void (*errHandler)(const wchar_t *what) = DefaultErrorHandler ;
//------------------------------

EEGANALYSIS_API int fnEEGAnalysis(void)
{
	//MessageBox(0,L"DDD",L"ddd",0);
	CWaitBoxDlg wbd;
	wbd.SetPrompt(_T("hahaha"));
	wbd.DoModal();
	return 42;
}

EEGANALYSIS_API void DLL_Init(){

	// Initialize GDI+.
	GdiplusStartupInput gdiplusStartupInput;
	GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
	_Module.Init ( NULL, (HINSTANCE)hDllModule );
	Config::g_configFile.read();//read configurations from config.conf
}
EEGANALYSIS_API void DLL_Finish(){
	GdiplusShutdown(gdiplusToken);
	Config::g_configFile.write();//save configurations
	FFTCalculator::DestoryInstance();
	DSACalculator::DestoryInstance();
	DataStore::DestroyInstance();

}

EEGANALYSIS_API void DS_AddChannel(unsigned int  eid, unsigned int reserveSize){
	//DataStore
	DataStore::GetInstance()->AddChannel(eid, reserveSize);

}

EEGANALYSIS_API unsigned int DS_EndChannel(void){
	return DataStore::GetInstance()->EndChannel();
}
EEGANALYSIS_API void DS_AddSingleData(double x){
	DataStore::GetInstance()->AddData2Channel(x);
}

EEGANALYSIS_API void DS_AddData(double *first, double *last){
	DataStore *ds = DataStore::GetInstance();
	while(first!=last){
		ds->AddData2Channel(*first);
		first++;
	}
}
EEGANALYSIS_API void DS_CleanAll(void){
	DataStore::GetInstance()->CleanAll();
}

EEGANALYSIS_API void EH_SetErrorHandlerW( void (*h)(const wchar_t *what)){
	errHandler = h;
}

EEGANALYSIS_API void DS_SetSamplingRate(unsigned long sr){
	DataStore::GetInstance()->SetSamplingRate(sr);
}

EEGANALYSIS_API void DS_SetChannelNameW(LPCTSTR name){
	DataStore::GetInstance()->SetChannelName(name);
}

EEGANALYSIS_API void DS_SetElectrodePos(double x, double y, int electrodeID){
	DataStore::GetInstance()->SetElectrodePos(x,y,electrodeID);
}

EEGANALYSIS_API void DS_SetRef(int type){
	//MessageBox(0,L"DDD",L"ddd",0);
	try{
		DataStore::GetInstance()->SetRef(type);
	}catch(EEG_Exceptions e){
		errHandler( e.what().c_str() );
	}
}

EEGANALYSIS_API int FFT_ShowFFTGraph(){
	AtlInitCommonControls(ICC_BAR_CLASSES);
	CMessageLoop theLoop;
	_Module.AddMessageLoop(&theLoop);

	CFFTMainFrame wndMain;

	if(wndMain.CreateEx() == NULL)
	{
		ATLTRACE(_T("Main window creation failed!\n"));
		return 0;
	}

	//wndMain.SetSource(FFTCalculator::GetInstance());

	wndMain.ShowWindow(SW_SHOW);

	int nRet = theLoop.Run();

	_Module.RemoveMessageLoop();
	return nRet;
}

EEGANALYSIS_API bool FFT_StartCalc(){
	
	if(!fft_cp)
	{
		errHandler(_T("EEGA: Invalid Parameters for FFT Calculator"));
		return false;
	}
	
//FFTCalculator::GetInstance()->SetSource(DataStore::GetInstance() );
	return FFTCalculator::GetInstance()->StartCalc(*fft_cp);
}

EEGANALYSIS_API void FFT_SetParameters(int *eids, unsigned int ch_count, unsigned int startpt, unsigned int endpt){
	if(fft_cp)
		delete fft_cp;
	fft_cp = new FFT_CalcParams;
	fft_cp->startpt = startpt;
	fft_cp->endpt = endpt;
	for(int i=0;i<ch_count;i++)
		fft_cp->channels_eid.push_back(*(eids+i));
//FFTCalculator::GetInstance()->SetSource(DataStore::GetInstance() );

}

EEGANALYSIS_API int  DSA_ShowDSAGraph(){
	if( dsa_views.empty() )
	{
		errHandler(_T("EEGA: No DSA Views"));
		return -1;
	}
	AtlInitCommonControls(ICC_BAR_CLASSES);
	CMessageLoop theLoop;
	_Module.AddMessageLoop(&theLoop);

	CDSAMainFrame wndMain;

	if(wndMain.CreateEx() == NULL)
	{
		ATLTRACE(_T("Main window creation failed!\n"));
		return 0;
	}
	for(size_t i=0;i<dsa_views.size();i++)
		wndMain.m_view.AddSubGraph(dsa_views[i]);

	wndMain.ShowWindow(SW_SHOW);

	int nRet = theLoop.Run();

	_Module.RemoveMessageLoop();
	dsa_views.clear();
	return nRet;
}

EEGANALYSIS_API void DSA_SetOnceParameters( int *eids, unsigned int count, unsigned int startpt, unsigned int endpt){
	if(dsa_cp)
		delete dsa_cp;
	dsa_cp = new DSA_CalcParams;
	dsa_cp->startpt = startpt;
	dsa_cp->endpt = endpt;
	for(UINT i=0;i<count;i++)
		dsa_cp->eids.push_back(*(eids+i));

}

EEGANALYSIS_API int  DSA_StartCalc()	//return the index in out, resultID
{
	if(!dsa_cp)
	{
		errHandler(_T("EEGA: Invalid Parameters for FFT Calculator"));
		return false;
	}
	//DSACalculator::GetInstance()->SetSource( DataStore::GetInstance() );
	return DSACalculator::GetInstance()->StartCalc(*dsa_cp);
}

EEGANALYSIS_API int  DSA_AddViewW( int resultID, wchar_t *title){
	DSA_SingleGraph sg;
	sg.signiture = resultID;
	_tcscpy(sg.title, title);
	dsa_views.push_back(sg);
	return 0;
}

EEGANALYSIS_API void  MAP_SetDefaultParameters( int *eids, unsigned int count, MAP_Type type, unsigned int midPt){
	if(map_des) delete map_des;
	map_des = new MAP_Descriptor();
	for(size_t i=0;i<count;i++)
		map_des->involvedEIDs.push_back(eids[i]);
	map_des->mid_PtIndex = midPt;
	map_des->type = type;
}

EEGANALYSIS_API int  MAP_ShowMAPGraph(){
	CMessageLoop theLoop;
	_Module.AddMessageLoop(&theLoop);

	CMAPMainFrame wndMain;

	if(wndMain.CreateEx() == NULL)
	{
		ATLTRACE(_T("Main window creation failed!\n"));
		return 0;
	}

	//wndMain.SetSource(FFTCalculator::GetInstance());

	wndMain.ShowWindow(SW_SHOW);
	int nRet = theLoop.Run();

	_Module.RemoveMessageLoop();
	return nRet;
}